package com.derbysoft.dswitch.adapter.ihg.dswitch2.translate;

import com.derbysoft.dswitch.adapter.ihg.common.utils.CloneUtils;
import com.derbysoft.dswitch.adapter.ihg.dswitch3.translate.Translator;
import com.derbysoft.dswitch.adapter.ihg.dto.AvailRoomStay;
import com.derbysoft.dswitch.adapter.ihg.dto.Error;
import com.derbysoft.dswitch.adapter.ihg.dto.OTAHotelAvailRS;
import com.derbysoft.dswitch.adapter.ihg.dto.RoomRate;
import com.derbysoft.remote.dswitch.core.*;
import com.derbysoft.remote.dswitch.generic.dto.UniqueIDDTO;
import com.derbysoft.remote.dswitch.hotel.dto.*;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.List;

@Component("ds2HotelAvailRSTranslator")
public class HotelAvailRSTranslator extends BaseTranslator
        implements Translator<OTAHotelAvailRS, GenericRS<HotelAvailRS>, GenericRQ<HotelAvailRQ>> {

    @Override
    public GenericRS<HotelAvailRS> translate(OTAHotelAvailRS otaHotelAvailRS, GenericRQ<HotelAvailRQ> request) {
        GenericRS<HotelAvailRS> response = new GenericRS<HotelAvailRS>();
        response.setHeader(new ResponseHeader(request.getHeader().getTaskId()));
        if (otaHotelAvailRS.getSuccess() == null
                && otaHotelAvailRS.getErrors() != null
                && !otaHotelAvailRS.getErrors().getError().isEmpty()) {
            response.setErrors(createErrors(otaHotelAvailRS));
            return response;
        }
        response.setSuccess(new SuccessDTO());
        HotelAvailRS hotelAvailRS = translateHotelAvailRS(otaHotelAvailRS, request.getPayload());
        setProviderChain(hotelAvailRS, request);
        response.setPayload(hotelAvailRS);
        return response;
    }

    private List<AvailRoomStayDTO> translateRoomStays(AvailRoomStay roomStay, HotelAvailRQ hotelAvailRQ) {
        List<AvailRoomStayDTO> availRoomStays = new ArrayList<AvailRoomStayDTO>();
        StayDateRangeDTO stayDateRange = hotelAvailRQ.getAvailCriteria().getStayDateRange();
        for (RoomRate roomRate : roomStay.getRoomRates().getRoomRate()) {
            com.derbysoft.dswitch.adapter.ihg.common.domain.RatePlan ratePlan = ratePlanRepository.loadByCode(roomRate.getRatePlanCode());
            if (ratePlan == null) {
                continue;
            }
            availRoomStays.add(translateAvailRoomStay(roomRate, roomStay, ratePlan, stayDateRange));
        }
        return availRoomStays;
    }

    private void setProviderChain(HotelAvailRS hotelAvailRS, final GenericRQ<HotelAvailRQ> request) {
        UniqueIDDTO chainID = CloneUtils.clone(request.getHeader().getDestinations().get(0).getUniqueID());
        for (AvailRoomStayDTO availRoomStayDTO : hotelAvailRS.getHotelAvailRoomStay().getRoomStays()) {
            availRoomStayDTO.setProviderChain(translateProviderChain(chainID));
        }
    }

    private HotelAvailRS translateHotelAvailRS(OTAHotelAvailRS otaHotelAvailRS, HotelAvailRQ hotelAvailRQ) {
        AvailRoomStay roomStay = otaHotelAvailRS.getRoomStays().getRoomStay().get(0);
        HotelAvailRS hotelAvailRS = new HotelAvailRS();
        hotelAvailRS.setHotelAvailRoomStay(translateHotelAvailRoomStay(roomStay, hotelAvailRQ));
        return hotelAvailRS;
    }

    private HotelAvailRoomStayDTO translateHotelAvailRoomStay(AvailRoomStay roomStay, HotelAvailRQ hotelAvailRQ) {
        HotelAvailRoomStayDTO hotelAvailRoomStayDTO = new HotelAvailRoomStayDTO();
        hotelAvailRoomStayDTO.setHotelRef(hotelAvailRQ.getAvailCriteria().getHotelRef());
        hotelAvailRoomStayDTO.setRoomStays(translateRoomStays(roomStay, hotelAvailRQ));
        return hotelAvailRoomStayDTO;
    }

    private ErrorsDTO createErrors(OTAHotelAvailRS otaHotelAvailRS) {
        ErrorsDTO errorsDTO = new ErrorsDTO();
        List<ErrorDTO> errors = new ArrayList<ErrorDTO>();
        List<Error> errorList = otaHotelAvailRS.getErrors().getError();
        for (Error error : errorList) {
            errors.add(translateError(error));
        }
        errorsDTO.setErrorList(errors);
        return errorsDTO;
    }

    private ErrorDTO translateError(Error error) {
        return new ErrorDTO(error.getCode(), error.getShortText(), provider);
    }
}